//
//  StatisticsDiaryViewModel.swift
//  imprint
//
//  Created by 小柠檬🍋 on 2025/2/15.
//

import Foundation
class StatisticsDiaryViewModel : BaseViewModel {
    @Published var items = [StatisticsDiaryBean]()
    @Published var status = ""
    
    private let stepMonth = 2
    private let deadLine = TimeInterval(1640966400000) //单位毫秒
    private var dictTitle :[Int:Bool] = [:]//避免重复。年标题问题
    
    func getData(_ isRefresh: Bool = false, _ type : IStatisticsType = IStatisticsType.DIARY) {
        var noMore = false
        let isPicture = type == IStatisticsType.DIARY
        requestList(isRefresh: isRefresh) {
            if isRefresh {
                self.dictTitle.removeAll()
            }
            let curTime = try await getNetTime() * 1000
            let list = try await BackupsManager.shared.getDelegateDiary()?.queryStatisticsDiary(userId: userManager.getUserId(), curTime: self.getStartTime(curTime,self.pageNo), endTime: self.getEndTime(curTime,self.pageNo), isPicture: isPicture) ?? []
            
            //key  :  yyyy-MM为key
            //values: [DiaryBean]
            //每个月组成一个数组，并且一天已经过滤为一个
            var dict : [String:[DiaryBean]] = [:]
            
            //将同一天处理为一个字典
            let grouped = Dictionary(grouping: list) { diary -> String in
                return TimeUtils.getDate(time: diary.time, format: "yyyy-MM-dd")
            }
            //过滤同一天的数据，生成一个新的[DiaryBean]
            let listDiary:[DiaryBean] = grouped.mapValues { list -> [DiaryBean] in
                //由于日记数据库查询是降序，但是我们当天显示的第一天，所以要取最后一个数据
                var valueBean = list.last!
                if isPicture {
                    // 检查是否有图片
                    if valueBean.listDiaryPicture?.isEmpty ?? true {
                        // 寻找第一个有图片的日记（从新到旧遍历）
                        if let firstWithImage = list.first(where: { !($0.listDiaryPicture?.isEmpty ?? true) }) {
                            valueBean = firstWithImage
                        }
                    }
                }
                return [valueBean]
            }.values.flatMap { $0 }
            
            //将同一个月数据整理一起
            listDiary.forEach { bean in
                let key = TimeUtils.getDate(time: bean.time, format: "yyyy-MM")
                var value = dict[key]
                if value == nil {
                    value = []
                }
                value?.append(bean)
                dict[key] = value
            }
            
            var listStatistics : [StatisticsDiaryBean] = []
            for (key, value) in dict {
                let components = key.components(separatedBy: "-")
                let year =  Int(components[0]) ?? 0
                var month = 0
                if components.count == 2 {
                    month = Int(components[1]) ?? 0
                }
                if year == 0 || month == 0 {
                    continue
                }
                var statisticsBean = StatisticsDiaryBean()
                statisticsBean.year = year
                statisticsBean.month = month
                statisticsBean.yearOrmonth = key
                var events: [String: DiaryBean] = [:]
                //value
                value.forEach {
                    events[TimeUtils.getDate(time: $0.time, format: "yyyy-MM-dd")] = $0
                }
                statisticsBean.events = events
                listStatistics.append(statisticsBean)
            }
            
            // 由于字典遍历，不会按照顺序来的，所以按时间降序排序
            listStatistics.sort(by: {
                if $0.year != $1.year {
                    return $0.year > $1.year
                }
                return $0.month > $1.month
            })
            //遍历处理是否显示年
            for index in listStatistics.indices {
                let year = listStatistics[index].year
                if self.dictTitle[year] != nil {
                    listStatistics[index].isYear = false
                } else {
                    listStatistics[index].isYear = true
                    self.dictTitle[year] = true
                }
            }
            
            noMore = self.getEndTime(curTime, self.pageNo) <= self.deadLine
            return listStatistics
        } noMore: { list in
            return noMore
        } suc: {
            if isRefresh && $0.isEmpty {
                self.status = "暂无数据"
            } else {
                self.status = ""
                self.items.append(contentsOf: $0)
            }
     
        } fail: {
            self.status = $0.message
        }
    }
    
    //单位是毫秒
    func getStartTime(_ curTime: TimeInterval, _ pageNo: Int) -> TimeInterval {
        let calendar = Calendar.current
        let date = Date(timeIntervalSince1970: curTime / 1000)
        
        var components = calendar.dateComponents([.year, .month], from: date)
        let currentYear = components.year!
        let currentMonth = components.month! // Swift 中月份是从 1 开始的
        
        var newYear = currentYear
        var newMonth = currentMonth - pageNo * stepMonth
        
        // 处理月份小于 1 的情况（即跨年）
        if newMonth < 1 {
            let yearsToSubtract = (-newMonth + 12) / 12 // 计算需要减去的整年数
            newYear = currentYear - yearsToSubtract
            newMonth += yearsToSubtract * 12 // 更新月份
        }
        
        // 设置新的年份和月份
        components.year = newYear
        components.month = newMonth
        
        // 获取这个月的最后一天
        if let newDate = calendar.date(from: components) {
            let lastDay = calendar.range(of: .day, in: .month, for: newDate)!.count
            components.day = lastDay
            components.hour = 23
            components.minute = 59
            components.second = 59
            components.nanosecond = 999
            
            let finalDate = calendar.date(from: components)!
            return finalDate.timeIntervalSince1970 * 1000
        }
        
        return curTime // 如果计算失败，返回原始时间
    }
    
    //单位是秒
    private func getEndTime(_ curTime: TimeInterval, _ pageNo: Int) -> TimeInterval {
        var time = getStartTime(curTime, pageNo + 1)
        time += 1//加1毫秒即可，因为取的是下一轮的开始时间，只+1毫秒就是上一轮的结束时间
        //时间不能低于这个值
        if (time < deadLine) {
            time = TimeInterval(deadLine)
        }
        return time
    }
    
}
